package com.yuke.cloud.service.omc.controller.frontend;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.yuke.cloud.common.core.support.BaseController;
import com.yuke.cloud.common.util.PublicUtil;
import com.yuke.cloud.common.util.wrapper.WrapMapper;
import com.yuke.cloud.common.util.wrapper.Wrapper;
import com.yuke.cloud.service.api.cmc.dto.CmsSysInfoDto;
import com.yuke.cloud.service.api.cmc.service.CmcFeignApi;
import com.yuke.cloud.service.omc.dto.OdsTeamInfoDto;
import com.yuke.cloud.service.omc.dto.OdsTeamIntentDto;
import com.yuke.cloud.service.omc.entity.OdsPayOrder;
import com.yuke.cloud.service.omc.entity.OdsTeam;
import com.yuke.cloud.service.omc.entity.OdsTeamIntent;
import com.yuke.cloud.service.omc.service.OdsPayOrderService;
import com.yuke.cloud.service.omc.service.OdsTeamGoodsService;
import com.yuke.cloud.service.omc.service.OdsTeamIntentService;
import com.yuke.cloud.service.omc.service.OdsTeamService;
import com.yuke.cloud.service.omc.utils.DateUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
* Created by zn on 2020/09/30.
*/
@Api(value = "WEB - OdsTeamIntentController", tags = "处理OdsTeamIntent相关请求", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@Slf4j
@RestController
@RequestMapping("/ods/teamIntent")
public class OdsTeamIntentController extends BaseController {
    @Resource
    private OdsTeamService odsTeamService;
    @Resource
    private OdsTeamController odsTeamController;
    @Resource
    private OdsTeamIntentService odsTeamIntentService;
    @Resource
    private OdsTeamGoodsService odsTeamGoodsService;
    @Resource
    private OdsBillController odsBillController;
    @Resource
    private OdsBillPayController odsBillPayController;
    @Resource
    private OdsPayOrderService odsPayOrderService;
    @Autowired
    private RedisTemplate redisTemplate;
    @Resource
    private CmcFeignApi cmcFeignApi;


    @PostMapping
    @ApiOperation(httpMethod = "POST", value = "新增一条记录")
    public Wrapper add(@ApiParam(name = "odsTeamIntent", value = "该数据记录的POJO") @RequestBody OdsTeamIntent odsTeamIntent) {
        odsTeamIntent.setIntentId(generateId());
        odsTeamIntentService.save(odsTeamIntent);
        return WrapMapper.ok();
    }

    @DeleteMapping("/{id}")
    @ApiOperation(httpMethod = "DELETE", value = "根据id删除一条记录")
    public Wrapper delete(@ApiParam(name = "id", value = "记录id") @PathVariable Long id) {
        odsTeamIntentService.deleteById(id);
        return WrapMapper.ok();
    }

    @PutMapping
    @ApiOperation(httpMethod = "PUT", value = "修改一条记录")
    public Wrapper update(@ApiParam(name = "odsTeamIntent", value = "需要修改的内容") @RequestBody OdsTeamIntent odsTeamIntent) {
        odsTeamIntentService.update(odsTeamIntent);
        return WrapMapper.ok();
    }

    @GetMapping("/{id}")
    @ApiOperation(httpMethod = "GET", value = "根据ID获取具体信息")
    public Wrapper<OdsTeamIntent> detail(@ApiParam(name = "id", value = "记录id") @PathVariable Long id) {
        OdsTeamIntent odsTeamIntent = odsTeamIntentService.findById(id);
        return WrapMapper.ok(odsTeamIntent);
    }

    @GetMapping
    @ApiOperation(httpMethod = "GET", value = "分页获取所有记录")
    public Wrapper<PageInfo<OdsTeamIntentDto>> list(@ApiParam(name = "page", value = "分页值", defaultValue = "0") @RequestParam(defaultValue = "0") Integer page,
                                                    @ApiParam(name = "size", value = "每分页返回的记录数", defaultValue = "0") @RequestParam(defaultValue = "0") Integer size,
                                                 @RequestParam(defaultValue = "0") Long teamId) {
        PageHelper.startPage(page, size);
        OdsTeamIntentDto odsIntentDto = new OdsTeamIntentDto();
        odsIntentDto.setTeamId(teamId);
        List<OdsTeamIntentDto> list = odsTeamIntentService.selectTeamIntentByCondition(odsIntentDto);
        PageInfo pageInfo = new PageInfo(list);

        list = odsTeamIntentService.getExtraInfo(list);
        pageInfo.setList(list);

        return WrapMapper.ok(pageInfo);
    }

    @PostMapping("/selectTeamIntent")
    @ApiOperation(httpMethod = "POST", value = "分页获取所有记录")
    public Wrapper<PageInfo<OdsTeamIntentDto>> selectTeamIntentByCondition(@ApiParam(name = "page", value = "分页值", defaultValue = "0") @RequestParam(defaultValue = "0") Integer page,
                                                                       @ApiParam(name = "size", value = "每分页返回的记录数", defaultValue = "0") @RequestParam(defaultValue = "0") Integer size,
                                                                       @ApiParam(name = "odsTeamIntentDto", value = "条件") @RequestBody OdsTeamIntentDto odsTeamIntentDto) {
        PageHelper.startPage(page, size);
        List<OdsTeamIntentDto> list = odsTeamIntentService.selectTeamIntentByCondition(odsTeamIntentDto);
        PageInfo pageInfo = new PageInfo(list);

        list = odsTeamIntentService.getExtraInfo(list);
        pageInfo.setList(list);
        return WrapMapper.ok(pageInfo);
    }

    /**
     * 团购时的订单和商品添加
     * @param odsTeamIntentDto
     * @return
     */
    @PostMapping("/addTeamIntent")
    @ApiOperation(httpMethod = "POST", value = "新增一条记录")
    public Wrapper addTeamIntent(@ApiParam(name = "odsTeamIntent", value = "该数据记录的POJO") @RequestBody OdsTeamIntentDto odsTeamIntentDto) {
        System.out.println("提交订单参数："+odsTeamIntentDto);

        // 先判断提交的数据是否为空
        if (odsTeamIntentDto == null || odsTeamIntentDto.getUserId() == null || odsTeamIntentDto.getTeamGoodsList() == null ||
                odsTeamIntentDto.getTeamGoodsList().size() <= 0 || odsTeamIntentDto.getPayType() == null) {
            return WrapMapper.error("订单数据无效");
        }
        //获取shopId
        Long shopId = odsTeamIntentDto.getShopId();
        //若shopId为空则返回无店铺信息
        if (shopId == null) {
            return WrapMapper.error("订单数据无效，没有店铺信息");
        }

        //阻止反复提交，短时间内重复提交
        Object uId = redisTemplate.opsForValue().get("TeamIntentAndUserId:" +odsTeamIntentDto.getUserId());
        if (uId != null){
            return WrapMapper.error("提交太频繁，不可重复提交！");
        }else{
            String id = "TeamIntentAndUserId:" +odsTeamIntentDto.getUserId();
            redisTemplate.opsForValue().set(id, odsTeamIntentDto.getUserId(), 10, TimeUnit.SECONDS);
        }

        //保存订单信息
        Byte payType = odsTeamIntentDto.getPayType();
        Map<String, String> mapResult = new HashMap<>();
        mapResult = odsTeamIntentService.saveTeamIntent(odsTeamIntentDto);
        mapResult.put("userId",odsTeamIntentDto.getUserId().toString());
        mapResult.put("payType",payType.toString());

        //调用支付模块
        Object result = payIntentOrder(mapResult);
        if (result != null){
            return WrapMapper.ok(result);
        }
        return WrapMapper.error();
    }

    /**
     * 团购时的订单结算
     * @param odsTeamIntentDto
     * @return
     */
    @PostMapping("/sumTeamIntent")
    @ApiOperation(httpMethod = "POST", value = "新增一条记录")
    public Wrapper sumTeamIntent(@ApiParam(name = "odsTeamIntent", value = "该数据记录的POJO") @RequestBody OdsTeamIntentDto odsTeamIntentDto) {
        System.out.println("提交订单参数：" + odsTeamIntentDto);
        // 先判断提交的数据是否为空
        if (odsTeamIntentDto == null || odsTeamIntentDto.getUserId() == null || odsTeamIntentDto.getTeamGoodsList() == null ||
                odsTeamIntentDto.getTeamGoodsList().size() <= 0 || odsTeamIntentDto.getPayType() == null || odsTeamIntentDto.getTeamId() != null) {
            return WrapMapper.error("订单数据无效");
        }

        OdsTeam odsTeam = odsTeamService.findById(odsTeamIntentDto.getTeamId());
        //判断时间是否已过期
        Date todayDate = new Date();
        if (todayDate.getTime() < odsTeam.getBeginTime().getTime() ){
            return WrapMapper.error("团购还未开始！");
        }
        if (todayDate.getTime() >= odsTeam.getEndTime().getTime()) {
            return WrapMapper.error("团购已经结束！");
        }
        //判断是否已经团购状态是否正常
        if (odsTeam.getTeamStatus() > 1){
            return WrapMapper.error("团购已经截止！");
        }

        Map<String, String> map = odsTeamIntentService.sumTeamIntent(odsTeamIntentDto);
        if (map == null){
            return WrapMapper.error("预定商品超过个人购买上限或预定商品超过销售计划限额。");
        }
        //判断订单金额是否满足

        Integer goodNum = Integer.parseInt(map.get("goodNum"));
        Integer totalpay = Integer.parseInt(map.get("totalpay"));

        if (odsTeam.getMinNum() > 0 && goodNum < odsTeam.getMinNum()){
            return WrapMapper.error("预定商品件数未达到要求。");
        }
        if (odsTeam.getMinMoney() > 0 && totalpay < odsTeam.getMinMoney()){
            return WrapMapper.error("预定商品金额未达到要求。");
        }

        return WrapMapper.ok(map);
    }

    /**
     * 拼单购时的订单和商品添加，拼单只要求件数
     * @param odsTeamIntentDto
     * @return
     */
    @PostMapping("/addShareOrder")
    @ApiOperation(httpMethod = "POST", value = "新增一条记录")
    public Wrapper addShareOrder(@ApiParam(name = "odsTeamIntent", value = "该数据记录的POJO") @RequestBody OdsTeamIntentDto odsTeamIntentDto) {
        System.out.println("提交拼单订单参数："+odsTeamIntentDto);

        // 先判断提交的数据是否为空
        if (odsTeamIntentDto == null || odsTeamIntentDto.getUserId() == null || odsTeamIntentDto.getTeamGoodsList() == null ||
            odsTeamIntentDto.getTeamGoodsList().size() <= 0 || odsTeamIntentDto.getPayType() == null || odsTeamIntentDto.getShopId() == null
               ) {
            return WrapMapper.error("订单数据无效");
        }

        //阻止反复提交，短时间内重复提交
        Object uId = redisTemplate.opsForValue().get("TeamIntentAndUserId:" +odsTeamIntentDto.getUserId());
        if (uId != null){
            return WrapMapper.error("提交太频繁，不可重复提交！");
        }else{
            String id = "TeamIntentAndUserId:" +odsTeamIntentDto.getUserId();
            redisTemplate.opsForValue().set(id, odsTeamIntentDto.getUserId(), 10, TimeUnit.SECONDS);
        }

        Long teamId=0L;
        OdsTeamInfoDto odsTeamDto = new OdsTeamInfoDto();
        odsTeamDto.setStorageId(odsTeamIntentDto.getTeamGoodsList().get(0).getStorageId());
        odsTeamDto.setTeamStatus((byte)1);
        odsTeamDto.setTeamType((byte)1);
        List<OdsTeamInfoDto> odsTeamDtos = odsTeamService.selectTeamInfo(odsTeamDto);
        if (odsTeamDtos == null || odsTeamDtos.size() < 1){
            odsTeamIntentDto.setTeamType((byte)1);
             teamId = addTeamInfo(odsTeamIntentDto);
        }
        else{
            //判断数量和金额是否满团，满了就关闭该团，开启下一个新团
            teamId = odsTeamDtos.get(0).getTeamId();
            Boolean tag = odsTeamController.closeTeamStatus(teamId);
            if (tag){
                teamId = addTeamInfo(odsTeamIntentDto);
            }

        }

        //保存订单信息
        odsTeamIntentDto.setTeamId(teamId);
        Byte payType = odsTeamIntentDto.getPayType();
        Map<String, String> mapResult = new HashMap<>();
        mapResult = odsTeamIntentService.saveShareOrder(odsTeamIntentDto);
        mapResult.put("userId",odsTeamIntentDto.getUserId().toString());
        mapResult.put("payType",payType.toString());

        //调用支付模块
        Object result = payIntentOrder(mapResult);
        if (result != null){
            return WrapMapper.ok(result);
        }
        return WrapMapper.error("提交支付时错误");
    }

    /**
     * 如果后期改为拼单商品由绑定商品取值，启用如下方法
     * @param odsTeamIntentDto
     */
    private void checkTeamIntent(OdsTeamIntentDto odsTeamIntentDto){
        //1.查找拼单商品信息 teamId storageId
        //2.查找拼单订单 storageId intentType=0
        //3.判断时间
        //4.判断最小购买数
        //5.判断库存
        //6.判断是否成团（依据成团要求是人数还是件数）
        //成团的，修改以前的订单信息，改变状态。
        //未成团的，新生成订单沿用之前的序列号，否则新生成序列号。
        //保存订单
    }
    /**
     * 支付订单
     * @param mapResult
     * @return
     */
    private Object payIntentOrder(Map<String,String> mapResult){
        Object result = null;
        if (PublicUtil.isNotEmpty(mapResult.get("pay_order_ids")) && PublicUtil.isNotEmpty(mapResult.get("totalpay"))) {
            String intentIds = mapResult.get("pay_order_ids");
            double totalPay = Double.parseDouble(mapResult.get("totalpay"));
            String payType = mapResult.get("payType");
            String userId = mapResult.get("userId");


            log.info("准备进入支付系统，intentIds={}, totalPay={}", intentIds, totalPay);
            Map<String, Object> map = new HashMap<String, Object>();
            // 支付宝
            if (payType.equals("2")) {
                map.put("paytype", "teamIntent");
                map.put("pay_bill_ids", intentIds);
                map.put("totalpay", totalPay / 100);

                JSONObject jsonObject1 = JSONObject.parseObject(JSON.toJSONString(map));
                // todo 调用支付接口
                log.info("调用支付接口传入参数" + jsonObject1);
                Wrapper wrapper = odsBillPayController.billAliPay(jsonObject1);
                log.info("调用支付接口返回参数" + wrapper);

                result = wrapper.getResult();
            } // 微信支付
            else if (payType.equals("3")) {
                map.put("paytype", "teamIntent");
                map.put("pay_bill_ids", intentIds);
                map.put("totalpay", Integer.valueOf(mapResult.get("totalpay")));

                JSONObject jsonObject1 = JSONObject.parseObject(JSON.toJSONString(map));
                try {
                    Wrapper wrapper = odsBillPayController.billWxPay(jsonObject1);
                    result = wrapper.getResult();
                    System.out.println("微信支付返回：" + result);
                } catch (Exception e) {
                    log.error(e.getMessage());
                    return WrapMapper.error("微信支付失败");
                }
            } // 账户余额支付
            else if (payType.equals("4")) {
                map.put("paytype", "teamIntent");
                map.put("pay_order_ids", intentIds);
                map.put("totalpay", Integer.valueOf(mapResult.get("totalpay")));
                map.put("userId", userId);
                JSONObject jsonObject1 = JSONObject.parseObject(JSON.toJSONString(map));
                try {
                    Wrapper wrapper = odsBillController.consumer(jsonObject1);
                    result = wrapper.getResult();
                    System.out.println(result);
                } catch (Exception e) {
                    log.error(e.getMessage());
                    return WrapMapper.error("账户支付失败");
                }
            }

        }
        return result;
    }

    /**
     * 生成拼单信息
     * @param odsTeamIntentDto
     * @return
     */
    private Long addTeamInfo(OdsTeamIntentDto odsTeamIntentDto){
        Long groupId = getLoginAuthDto().getGroupId();
        if (groupId == null){
            groupId = 220839532667469824L;
        }
        Integer teamNum = 3;
        Integer teamDay = 2;
        Integer sysInfoType = 22;
        CmsSysInfoDto cmsSysInfoDto = cmcFeignApi.getSysInfoDtoByType(groupId,sysInfoType);
        if (cmsSysInfoDto != null){
            JSONObject jsonObject = JSON.parseObject(cmsSysInfoDto.getInfoValue());
            teamNum = Integer.parseInt(jsonObject.get("teamNum").toString());
            teamDay = Integer.parseInt(jsonObject.get("teamDay").toString());
        }
        Date nowDate = new Date();
        Long teamId = generateId();
        OdsTeam odsTeam = new OdsTeam();
        odsTeam.setTeamId(teamId);
        odsTeam.setTeamType((byte)1);
        odsTeam.setTeamStatus((byte)1);
        odsTeam.setBeginTime(nowDate);
        odsTeam.setEndTime(DateUtil.nDaysAfter(nowDate,teamDay));
        odsTeam.setMinMoney(0);
        odsTeam.setMinNum(1);
        odsTeam.setSpecId(odsTeamIntentDto.getTeamGoodsList().get(0).getSpecId());
        odsTeam.setStorageId(odsTeamIntentDto.getTeamGoodsList().get(0).getStorageId());
        odsTeam.setWarehouseId(odsTeamIntentDto.getTeamGoodsList().get(0).getWarehouseId());
        odsTeam.setStartTime(nowDate);
        odsTeam.setTeamNum(teamNum);
        odsTeam.setTeamName("拼单商品团");
        int num = odsTeamService.saveTeamInfo(odsTeam);
        if (num > 0){
            return teamId;
        }
        return 0L;
    }

    /**
     * 用户取消订单操作
     */
    @PostMapping("/cancelIntentOrder")
    public Wrapper cancelIntentOrder(@RequestBody OdsTeamIntent odsTeamIntent) {
        if (odsTeamIntent == null || odsTeamIntent.getIntentId() == null){
            return WrapMapper.error("参数错误！");
        }
        List<OdsTeamIntent> odsTeamIntents = odsTeamIntentService.select(odsTeamIntent);
        if (odsTeamIntents == null || odsTeamIntents.size() < 1){
            return WrapMapper.error("未找到该订单！");
        }
        odsTeamIntent = odsTeamIntents.get(0);
        //1判断未付款，可以取消订单
        if (odsTeamIntent.getIntentStatus().equals((byte)0) && odsTeamIntent.getPayStatus().equals((byte)0)){
            odsTeamIntent.setIntentStatus((byte)3);
            odsTeamIntentService.update(odsTeamIntent);
            return WrapMapper.ok("已提交取消订单信息！");
        }

        //2判断订单状态，拼团开始,已付款，不能取消。
        if (odsTeamIntent.getIntentStatus().equals((byte)1) && odsTeamIntent.getPayStatus().equals((byte)1)){
            return WrapMapper.error("拼单正在进行中，不能取消订单！");
        }

        //3已成团、发货中不能取消。
        if (odsTeamIntent.getIntentStatus().equals((byte)2) && odsTeamIntent.getPayStatus().equals((byte)1) &&
                odsTeamIntent.getShippingStatus().equals((byte)2)){
            return WrapMapper.error("拼单发货中，不能取消订单！");
        }

        //4已成团未发货、可以取消订单，退款
        if (odsTeamIntent.getIntentStatus().equals((byte)2) && odsTeamIntent.getPayStatus().equals((byte)1) &&
                odsTeamIntent.getShippingStatus()< 2){
            odsTeamIntent.setIntentStatus((byte)3);
            odsTeamIntentService.update(odsTeamIntent);
            refoundIntentOrder(odsTeamIntent);
            return WrapMapper.ok("已提交退款信息，请查收付款时的支付账号");
        }

        //5已成团,已发货，已收货可以取消订单，先提交退款申请，仓库收到货以后退款
        if (odsTeamIntent.getIntentStatus().equals((byte)2) && odsTeamIntent.getPayStatus().equals((byte)1) &&
                odsTeamIntent.getShippingStatus().equals((byte)3)){
            odsTeamIntent.setIntentStatus((byte)4);
            odsTeamIntentService.update(odsTeamIntent);
            return WrapMapper.ok("已提交退款信息，仓库收到货以后退款！");
        }

        return WrapMapper.error("取消拼单被拒绝，请联系管理员！");
    }
    /**
     * 取消订单退款
     * @param odsTeamIntent
     * @return
     */
    @PostMapping("/refoundIntentOrder")
    public Object refoundIntentOrder(OdsTeamIntent odsTeamIntent) {
        int ret = 0;
        Map map = new HashMap();

        double amountPaid = Double.parseDouble(odsTeamIntent.getAmountPaid().toString());

        //从支付表找找拼单订单的付款记录
        Example example = new Example(OdsPayOrder.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andLike("orderIds", "%" + odsTeamIntent.getIntentId() + "%");
        List<OdsPayOrder> odsPayOrders = odsPayOrderService.selectByExample(example);
        OdsPayOrder odsPayOrder = odsPayOrders.get(0);
        String payId = odsPayOrder.getPayId().toString();

        // 支付宝原路退回
        if (odsTeamIntent.getPayType().toString().equals("2")) {
            map.put("refund_amount", amountPaid / 100);
            map.put("out_trade_no", odsTeamIntent.getIntentId());
            map.put("out_request_no",payId);
            JSONObject jsonObject = new JSONObject(map);
            ret = odsBillPayController.aliRefund(jsonObject);

        } else if (odsTeamIntent.getPayType().toString().equals("3")) {  // 微信支付原路退回
            map.put("refund_amount", amountPaid);
            if (odsPayOrder != null && odsPayOrder.getAmountPaid() != null && odsPayOrder.getAmountPaid() > 0) {
                map.put("total_fee", odsPayOrder.getAmountPaid());
            } else {
                map.put("total_fee", amountPaid);
            }
            map.put("out_trade_no", odsTeamIntent.getIntentId());
            map.put("out_refund_no",payId);
            JSONObject jsonObject = new JSONObject(map);
            ret = odsBillPayController.wxPayBack(jsonObject);

        }

        return ret;
    }
    /**
     * 拼购时的订单结算
     * @param odsTeamIntentDto
     * @return
     */
    @PostMapping("/accountTeamIntent")
    @ApiOperation(httpMethod = "POST", value = "新增一条记录")
    public Wrapper accountTeamIntent(@ApiParam(name = "odsTeamIntent", value = "该数据记录的POJO") @RequestBody OdsTeamIntentDto odsTeamIntentDto) {
        System.out.println("提交订单参数：" + odsTeamIntentDto);
        // 先判断提交的数据是否为空
        if (odsTeamIntentDto == null || odsTeamIntentDto.getUserId() == null || odsTeamIntentDto.getTeamGoodsList() == null ||
                odsTeamIntentDto.getTeamGoodsList().size() <= 0 ) {
            return WrapMapper.error("订单数据无效");
        }


        Map<String, String> map = odsTeamIntentService.accountTeamIntent(odsTeamIntentDto);
        if (map == null){
            return WrapMapper.error("预定商品计算错误。");
        }
        //判断订单金额是否满足

        return WrapMapper.ok(map);
    }


}
